package com.yihecode.camera.ai.web;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yihecode.camera.ai.entity.Algorithm;
import com.yihecode.camera.ai.entity.Camera;
import com.yihecode.camera.ai.entity.Report;
import com.yihecode.camera.ai.entity.VideoPlay;
import com.yihecode.camera.ai.service.*;
import com.yihecode.camera.ai.utils.JsonResult;
import com.yihecode.camera.ai.utils.JsonResultUtils;
import com.yihecode.camera.ai.utils.PageResult;
import com.yihecode.camera.ai.utils.PageResultUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 视频流播放管理
 *
 * @author zhoumingxing
 * @mail 465769438@qq.com
 */
@SaCheckLogin
@Controller
@RequestMapping({"/stream"})
public class StreamController {

    //
    @Autowired
    private CameraService cameraService;

    //
    @Autowired
    private ConfigService configService;

    //
    @Autowired
    private AlgorithmService algorithmService;

    //
    @Autowired
    private ReportService reportService;

    //
    @Autowired
    private VideoPlayService videoPlayService;

    /**
     *
     * @return
     */
    @GetMapping({"", "/"})
    public String index(ModelMap modelMap) {
        String streamType = configService.getByValTag("streamType");  // 推流类型
        String streamUrl = configService.getByValTag("streamUrl");
        modelMap.addAttribute("streamUrl", streamUrl);
        modelMap.addAttribute("wsUrl", configService.getByValTag("wsUrl"));
        modelMap.addAttribute("uid", IdUtil.fastSimpleUUID());

        // 开始和结束毫秒值
        long startMills = DateUtil.truncate(new Date(), DateField.DAY_OF_MONTH).getTime();
        long endMills = DateUtil.truncate(DateUtil.offsetDay(new Date(), 1), DateField.DAY_OF_MONTH).getTime();
        int counter = reportService.getCounter(startMills, endMills);
        modelMap.addAttribute("counter", counter);

        // 活动视频流
        List<VideoPlay> videoPlays = videoPlayService.list();
        if(videoPlays == null) {
            videoPlays = new ArrayList<>();
        }

        // List<Camera> cameraActiveList = cameraService.listActives();
        // int cameraSize = cameraActiveList.size();
        int cameraSize = videoPlays.size();
        if(cameraSize <= 1) {
            modelMap.addAttribute("showNum", 1); // 展示窗口数量
        } else {
            modelMap.addAttribute("showNum", 4); // 展示窗口数量
        }

        //
        Map<Long, String> cameraNames = cameraService.toMap();

        //
        Map<Long, String> algorithmNames = algorithmService.toMap();

        // 默认查询当日最近3条告警
        List<Report> reportList = reportService.listNewly(3);
        if(reportList != null) {
            List<Map<String, Object>> dataList = new ArrayList<>();
            for(Report report : reportList) {
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("id", report.getId());
                dataMap.put("params", report.getParams());
                dataMap.put("cameraName", cameraNames.get(report.getCameraId()));
                dataMap.put("algorithmName", algorithmNames.get(report.getAlgorithmId()));
                dataMap.put("wareName", "");
                dataMap.put("alarmTime", (report.getCreatedAt() == null) ? "" : DateUtil.format(report.getCreatedAt(), "MM/dd HH:mm"));
                dataList.add(dataMap);
            }
            modelMap.addAttribute("reportList", dataList);
        }

        //
        if(StrUtil.isBlank(streamType)) {
            return "stream/index_tj";
        }
        return "stream/index";
    }

    /**
     *
     * @param id
     * @param modelMap
     * @return
     */
    @GetMapping({"/form"})
    public String form(String id, ModelMap modelMap) {
        // 数据列表
        List<Map<String, Object>> dataList = new ArrayList<>();

        // 数据流类型
        String streamType = configService.getByValTag("streamType");
        if(StrUtil.isBlank(streamType)) {
            // 默认java推流
            List<Camera> cameraList = this.cameraService.listData();
            if (cameraList != null) {
                for (Camera camera : cameraList) {
                    //
                    Map<String, Object> dataMap = new HashMap<>();
                    dataMap.put("id", camera.getId());
                    dataMap.put("name", (camera == null) ? "未知(空)" : camera.getName());
                    dataList.add(dataMap);
                }
            }
        }  else {
            // 算法推流
            List<VideoPlay> videoPlays = videoPlayService.list();
            if(videoPlays != null) {
                for(VideoPlay videoPlay : videoPlays) {
                    Camera camera = cameraService.getById(videoPlay.getCameraId());

                    //
                    Map<String, Object> dataMap = new HashMap<>();
                    dataMap.put("id", videoPlay.getCameraId());
                    dataMap.put("name", (camera == null) ? "未知(空)" : camera.getName());
                    dataList.add(dataMap);
                }
            }
        }

        //
        modelMap.addAttribute("cameraList", dataList);
        modelMap.addAttribute("id", id);
        return "stream/form";
    }

    /**
     *
     * @return
     */
    @GetMapping("/v2")
    public String indexv2(ModelMap modelMap) {
        String streamUrl = configService.getByValTag("streamUrl");
        modelMap.addAttribute("streamUrl", streamUrl);
        modelMap.addAttribute("cameraList", cameraService.listData());
        modelMap.addAttribute("uid", IdUtil.fastSimpleUUID());
        modelMap.addAttribute("wsUrl", configService.getByValTag("wsUrl"));

        // 开始和结束毫秒值
        long startMills = DateUtil.truncate(new Date(), DateField.DAY_OF_MONTH).getTime();
        long endMills = DateUtil.truncate(DateUtil.offsetDay(new Date(), 1), DateField.DAY_OF_MONTH).getTime();
        int counter = reportService.getCounter(startMills, endMills);
        modelMap.addAttribute("counter", counter);

        return "stream2/index";
    }

    /**
     * 统计配置
     * @param id
     * @param modelMap
     * @return
     */
    @GetMapping({"/formConfig"})
    public String formConfig(String id, ModelMap modelMap) {
        List<Algorithm> algorithmList = algorithmService.listUsed();
        if(algorithmList == null) {
            algorithmList = new ArrayList<>();
        }

        //
        for(Algorithm algorithm : algorithmList) {
            if(algorithm.getStaticsFlag() != null && algorithm.getStaticsFlag() == 1) {
                algorithm.setStaticsFlagVal("checked");
            } else {
                algorithm.setStaticsFlagVal("");
            }
        }
        modelMap.addAttribute("algorithmList", algorithmList);
        return "stream/form_config";
    }

    /**
     * 保存统计配置
     * @param ids
     * @return
     */
    @PostMapping({"/formConfig"})
    @ResponseBody
    public JsonResult formConfig(String ids) {
        JSONArray array = JSON.parseArray(ids);
        int len = array.size();

        //
        if(len > 8) {
            return JsonResultUtils.fail("最多支持勾选8个");
        }

        //
        List<Long> idList = new ArrayList<>();
        for(int i = 0; i < len; i++) {
            idList.add(array.getLongValue(i));
        }

        // 更新统计标识
        algorithmService.updateStaticsFlag(idList);

        return JsonResultUtils.success();
    }

    /**
     * 统计算法
     * @return
     */
    @PostMapping({"/statics/algorithms"})
    @ResponseBody
    public JsonResult staticsAlgorithms() {
        List<Algorithm> algorithmList = algorithmService.listUsed();
        if(algorithmList == null) {
            algorithmList = new ArrayList<>();
        }

        // 开始和结束毫秒值
        long startMills = DateUtil.truncate(new Date(), DateField.DAY_OF_MONTH).getTime();
        long endMills = DateUtil.truncate(DateUtil.offsetDay(new Date(), 1), DateField.DAY_OF_MONTH).getTime();

        //
        List<Algorithm> showAlgorithmList = new ArrayList<>();
        for(Algorithm algorithm : algorithmList) {
            if(algorithm.getStaticsFlag() != null && algorithm.getStaticsFlag() == 1) {
                Integer counter = reportService.getAlgorithmCounter(algorithm.getId(), startMills, endMills);
                algorithm.setStaticsFlagVal("" + counter);
                showAlgorithmList.add(algorithm);
            }
        }
        return JsonResultUtils.success(showAlgorithmList);
    }

    /**
     * 打开播放选择列表
     * @return
     */
    @GetMapping("/select_play")
    public String selectPlayPage(ModelMap modelMap) {
        // 查询视频播放地址
        String streamUrl = configService.getByValTag("streamUrl");
        // 查询端口
        String videoPorts = configService.getByValTag("video_ports");
        // 播放地址列表
        List<Map<String, String>> dataList = new ArrayList<>();
        if(StrUtil.isNotBlank(videoPorts)) {
            String[] videoPortsArr = videoPorts.split(",");
            for(String videoPort : videoPortsArr) {
                Map<String, String> dataMap = new HashMap<>();
                dataMap.put("videoPort", videoPort);
                dataMap.put("videoUrl", streamUrl + ":" + videoPort + "/live");
                dataList.add(dataMap);
            }
        }
        modelMap.addAttribute("videoUrls", dataList);
        return "stream/select_play";
    }

    /**
     * 查询已配置播放列表
     * @return
     */
    @PostMapping("/play_list")
    @ResponseBody
    public PageResult playList() {
        // 查询视频播放地址
        String streamUrl = configService.getByValTag("streamUrl");
        // 查询已配置播放端口
        List<VideoPlay> videoPlays = videoPlayService.list();
        // 数据数据
        List<Map<String, Object>> dataList = new ArrayList<>();
        if(videoPlays != null) {
            for(VideoPlay videoPlay : videoPlays) {
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("cameraId", videoPlay.getCameraId());
                dataMap.put("playUrl", streamUrl + ":" + videoPlay.getVideoPort() + "/live");
                // 查询摄像头名称
                Camera camera = cameraService.getById(videoPlay.getCameraId());
                if(camera == null || StrUtil.isBlank(camera.getName())) {
                    dataMap.put("cameraName", "未知(空)");
                } else {
                    dataMap.put("cameraName", camera.getName());
                }
                dataList.add(dataMap);
            }
        }
        return PageResultUtils.success(null, dataList);
    }

    /**
     * 查询摄像头列表，按照已配置播放排序
     * @return
     */
    @PostMapping("/camera_list")
    @ResponseBody
    public PageResult cameraList(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer limit) {
        // 播放地址前缀
        String streamUrl = configService.getByValTag("streamUrl");

        // 查询已配置摄像头与端口关联
        List<VideoPlay> videoPlays = videoPlayService.list();
        Map<Long, Integer> videoPortMap = new HashMap<>();
        if(videoPlays != null) {
            for(VideoPlay videoPlay : videoPlays) {
                videoPortMap.put(videoPlay.getCameraId(), videoPlay.getVideoPort());
            }
        }

        // 查询摄像头列表
        IPage<Camera> pageResult = cameraService.listPageAndOrderVideoPlay(new Page<Camera>(page, limit));
        // 数据结果
        List<Map<String, Object>> dataList = new ArrayList<>();
        if(pageResult.getRecords() != null) {
            for(Camera camera : pageResult.getRecords()) {
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("cameraId", camera.getId());
                dataMap.put("cameraName", camera.getName());
                if(videoPortMap.containsKey(camera.getId())) {
                    dataMap.put("playUrl", streamUrl + ":" + videoPortMap.get(camera.getId()) + "/live");
                } else {
                    dataMap.put("playUrl", "");
                }
                dataList.add(dataMap);
            }
        }

        return PageResultUtils.success(pageResult.getTotal(), dataList);
    }

    /**
     * 停止视频流
     * @param cameraId
     * @return
     */
    @PostMapping("/stop")
    @ResponseBody
    public JsonResult stopStream(Long cameraId) {
        // 停止播放并释放端口
        cameraService.updateVideoPlay(cameraId, 0, 0);
        //
        return JsonResultUtils.success();
    }

    /**
     * 播放视频流
     * @param cameraId
     * @return
     */
    @PostMapping("/start")
    @ResponseBody
    public JsonResult startStream(Long cameraId, Integer videoPort) {
        //
        if(videoPort == null) {
            return JsonResultUtils.fail("请选择播放地址");
        }

        // 停止播放并释放端口
        Map<String, Object> retMap = cameraService.updateVideoPlay(cameraId, 1, videoPort);
        if(Convert.toInt(retMap.get("code"), 0) == 200) {
            return JsonResultUtils.success();
        }
        return JsonResultUtils.fail(Convert.toStr(retMap.get("msg")));
    }
}